from rest_framework.views import APIView
from common.exceptions import JsonAPIException
from common.error_code import ErrCode, AdmErrCode
from tuntun.authentication import AdmJSONWebTokenAuthentication
from rest_framework.parsers import JSONParser
from rest_framework.permissions import BasePermission
from django.http import HttpResponse
from django.core.paginator import Paginator



class BaseAPIView(APIView):
    """
    Base API View
    """
    resp = {}

    def process_page(self, rows, offset, limit):
        print(rows, offset, limit)
        if isinstance(rows, list):
            count = len(rows)
        else:
            count = rows.count()
        if offset == -1 and limit == -1:
            objs = rows
        else:
            try:
                paginator = Paginator(rows, limit)
                req_page = offset // limit + 1
                objs = paginator.page(req_page).object_list
            except:
                count = 0
                objs = []

        return count, objs

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """
        if request.authenticators and not request.successful_authenticator:
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg='不允许匿名访问', status=401)
        raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg='权限拒绝', status=403)

    def only_allow_self_user_check(self, request, user_id):
        """
        传入request和路由里获取到的user_id
        """
        self.accessor_user = request.user
        self.user_id = user_id
        self.resp = {}
        if self.accessor_user.id != self.user_id:
            raise JsonAPIException(code=ErrCode.ACCESS_NOT_ALLOWED.name,
                                   msg=ErrCode.ACCESS_NOT_ALLOWED.value,
                                   status=403)

    def options(self, request, *args, **kwargs):
        print(request.META)
        response = HttpResponse()
        response['Access-Control-Allow-Origin'] = '*'
        response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
        response['Access-Control-Max-Age'] = 1000
        # note that '*' is not valid for Access-Control-Allow-Headers
        response['Access-Control-Allow-Headers'] = request.META.get('HTTP_ACCESS_CONTROL_REQUEST_HEADERS', 'content-type')
        return response


class AdmInSuperUserGroup(BasePermission):
    def has_permission(self, request, view):
        from tuntun.settings import DJANGO_SUPER_USER_GROUP_NAME
        from django.contrib.auth.models import User as DjangoUser
        from django.contrib.auth.models import Group as DjangoGroup
        user = DjangoUser.objects.get(pk=request.user.id)
        super_user_group, _ = DjangoGroup.objects.get_or_create(name=DJANGO_SUPER_USER_GROUP_NAME)
        # print(super_user_group)
        if super_user_group in user.groups.all():  # [g.id for g in user.groups]:
            return True
        else:
            raise JsonAPIException(code=AdmErrCode.NO_SUPER_USER_PERMISSION.name, msg=AdmErrCode, status=400)


class BaseAdmAPIView(APIView):
    """Base Adm API View"""
    resp = {}
    authentication_classes = (AdmJSONWebTokenAuthentication, )
    permission_classes = (AdmInSuperUserGroup,)

    def permission_denied(self, request, message=None):
        """
        If request is not permitted, determine what kind of exception to raise.
        """
        if request.authenticators and not request.successful_authenticator:
            raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg='不允许匿名访问', status=401)
        raise JsonAPIException(code=ErrCode.AUTH_FAILED.name, msg='权限拒绝', status=403)

    def page_objects(self, request, objects, page=None, size=None):
        if page and size:
            page = int(page)
            size = int(size)
        else:
            try:
                page = int(request.GET.get('page'))
                size = int(request.GET.get('size'))
            except:
                page = 1
                size = 15

        p = Paginator(objects, size, allow_empty_first_page=True)
        return p.count, p.page(page).object_list
